package com.plpm.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.Session;
import org.apache.iotdb.session.pool.SessionPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.plpm.config.IoTDBConfig;

import lombok.extern.slf4j.Slf4j;

/**
 * IoTDB数据存储服务（表模型）
 * 使用IoTDB的表模型进行数据存储和查询，支持ALIGN BY DEVICE语法
 *
 * @author PLPM Team
 * @version 1.0
 */
@Slf4j
@Service
public class IoTDBService {

    @Autowired
    private IoTDBConfig iotdbConfig;

    @Autowired(required = false)
    private SessionPool sessionPool;


    @Value("${iotdb.database}")
    private String database;
    @Value("${iotdb.tablename}")
    private String tableName;

    //储存fileRecordVO的信息
    private static final String FILE_INFO_DEVICE = "root.plpm.file_info";
    //储存表结构字段
    private static final String FILE_CONTENT_DEVICE = "root.plpm.file_content";

    /**
     * 初始化IoTDB表模型
     * 手动调用此方法来初始化IoTDB的表模型结构
     */
    @PostConstruct
    public void initializeTableModel() throws IoTDBConnectionException, StatementExecutionException {
        if (sessionPool == null) {
            log.warn("IoTDB SessionPool不可用，跳过表模型初始化");
            return;
        }

        try {
            log.info("正在初始化IoTDB表模型，数据库: {}", database);
            log.info("IoTDB连接信息: {}:{}", iotdbConfig.getHost(), iotdbConfig.getPort());

            // 设置表模型
            setTableModel();

            // 创建数据库
            createDataBase();

            // 创建表
            createTable();

            log.info("IoTDB表模型初始化成功");
        } catch (Exception e) {
            log.error("初始化IoTDB表模型失败", e);
            log.warn("应用程序将在没有IoTDB连接的情况下继续运行");
        }
    }

    /**
     * 设置IoTDB为表模型
     * 使用单独的Session来设置SQL方言，因为SessionPool不支持SET SQL_DIALECT
     */
    private void setTableModel() {
        try {
            log.info("正在设置IoTDB为表模型...");
            
            // 使用单独的Session来设置SQL方言
            Session tempSession = new Session.Builder()
                    .host(iotdbConfig.getHost())
                    .port(iotdbConfig.getPort())
                    .username(iotdbConfig.getUsername())
                    .password(iotdbConfig.getPassword())
                    .build();
            
            try {
                tempSession.open();
                
                // 设置SQL方言为TABLE
                String setDialectSql = "SET SQL_DIALECT=TABLE";
                tempSession.executeNonQueryStatement(setDialectSql);
                log.info("IoTDB SQL方言已设置为TABLE");
                
                // 验证表模型是否真正生效 - 尝试创建测试数据库
                try {
                    String testDbName = "test_table_model_" + System.currentTimeMillis();
                    String testCreateSql = "CREATE DATABASE " + testDbName;
                    tempSession.executeNonQueryStatement(testCreateSql);
                    log.info("表模型验证成功 - 测试数据库创建成功: {}", testDbName);
                    
                    // 清理测试数据库
                    try {
                        String testDropSql = "DROP DATABASE " + testDbName;
                        tempSession.executeNonQueryStatement(testDropSql);
                        log.info("测试数据库已清理: {}", testDbName);
        } catch (Exception e) {
                        log.warn("清理测试数据库失败: {}", e.getMessage());
                    }
                    
                } catch (Exception e) {
                    log.warn("表模型验证失败，可能仍在使用树模型: {}", e.getMessage());
                    throw new RuntimeException("表模型设置验证失败", e);
                }
                
                log.info("IoTDB连接验证成功，表模型(TABLE)设置完成");
                
            } finally {
                // 确保临时Session被关闭
                if (tempSession != null) {
                    try {
                        tempSession.close();
                    } catch (Exception e) {
                        log.warn("关闭临时Session失败: {}", e.getMessage());
                    }
                }
            }

        } catch (Exception e) {
            log.error("设置表模型失败: {}", e.getMessage());
            throw new RuntimeException("无法设置IoTDB为表模型，请检查IoTDB服务器配置", e);
        }
    }


    /**
     * 创建数据库
     * 在表模型下创建数据库
     */
    private void createDataBase() throws IoTDBConnectionException, StatementExecutionException {
        try {
            log.info("正在创建数据库: {}", database);
            
            // 使用单独的Session来创建数据库，确保使用表模型
            Session tempSession = new Session.Builder()
                    .host(iotdbConfig.getHost())
                    .port(iotdbConfig.getPort())
                    .username(iotdbConfig.getUsername())
                    .password(iotdbConfig.getPassword())
                    .build();
            
            try {
                tempSession.open();
                
                // 设置SQL方言为TABLE（确保使用表模型）
                String setDialectSql = "SET SQL_DIALECT=TABLE";
                tempSession.executeNonQueryStatement(setDialectSql);
                
                // 创建数据库
                String sql = "CREATE DATABASE " + database;
                tempSession.executeNonQueryStatement(sql);
                log.info("数据库创建成功: {}", database);
                
            } finally {
                if (tempSession != null) {
                    try {
                        tempSession.close();
                    } catch (Exception e) {
                        log.warn("关闭临时Session失败: {}", e.getMessage());
                    }
                }
            }
            
        } catch (IoTDBConnectionException | StatementExecutionException e) {
            if (e.getMessage().contains("already exists")) {
                log.info("数据库已存在: {}，跳过创建步骤", database);
            } else {
                log.error("创建数据库失败: {}", database, e);
                throw e;
            }
        }
    }


    /**
     * 创建表
     * 在表模型下创建表结构
     */
    private void createTable() throws IoTDBConnectionException, StatementExecutionException {
        try {
            log.info("开始创建表结构...");

            // 创建文件记录表
            createFileRecordTable();

            log.info("表结构创建完成");

        } catch (IoTDBConnectionException | StatementExecutionException e) {
            log.error("创建表结构失败", e);
            throw e;
        }
    }

    /**
     * 创建文件记录表
     * 在表模型下创建文件记录表结构
     */
    private void createFileRecordTable() throws IoTDBConnectionException, StatementExecutionException {
        try {
            log.info("正在创建文件记录表: {}", tableName);
            
            // 使用单独的Session来创建表，确保使用表模型
            Session tempSession = new Session.Builder()
                    .host(iotdbConfig.getHost())
                    .port(iotdbConfig.getPort())
                    .username(iotdbConfig.getUsername())
                    .password(iotdbConfig.getPassword())
                    .build();
            
            try {
                tempSession.open();
                
                // 设置SQL方言为TABLE（确保使用表模型）
                String setDialectSql = "SET SQL_DIALECT=TABLE";
                tempSession.executeNonQueryStatement(setDialectSql);
                
                // 使用目标数据库
                String useDbSql = "USE " + database;
                tempSession.executeNonQueryStatement(useDbSql);
                log.info("已切换到数据库: {}", database);
                
                // 构建CREATE TABLE语句 - IoTDB表模型语法
                // 根据官方文档示例，使用正确的语法
                StringBuilder sql = new StringBuilder();
                sql.append("CREATE TABLE ").append(tableName).append(" (");
//                sql.append("time TIMESTAMP TIME, ");  // 正确的时间列语法，不写也会自动创建
                sql.append("record_id STRING TAG, ");  // 唯一标识字段（UUID），使用TAG以便在DELETE的WHERE条件中使用
                sql.append("file_name STRING FIELD, ");
                sql.append("project_no STRING FIELD, ");
                sql.append("plane_id STRING FIELD, ");
                sql.append("plane_no STRING FIELD, ");
                sql.append("place STRING FIELD, ");
                sql.append("company STRING FIELD, ");
                sql.append("product_phase INT32 FIELD, ");
                sql.append("data_type_first INT32 FIELD, ");
                sql.append("data_type_second INT32 FIELD, ");
                sql.append("data_source STRING FIELD, ");
                sql.append("start_time INT64 FIELD, ");
                sql.append("engine_id STRING FIELD, ");
                sql.append("engine_no STRING FIELD, ");
                sql.append("channel_no STRING FIELD, ");
                sql.append("device_no STRING FIELD, ");
                sql.append("engine_place STRING FIELD, ");
                sql.append("ecu_id STRING FIELD, ");
                sql.append("ecu_no STRING FIELD, ");
                sql.append("ecu_sys_id STRING FIELD, ");
                sql.append("ecu_sys_no STRING FIELD, ");
                sql.append("subject STRING FIELD, ");
                sql.append("remark STRING FIELD, ");
                sql.append("check_code STRING FIELD, ");
                sql.append("sync_data_source INT32 FIELD, ");
                sql.append("sync_status INT32 FIELD, ");
                sql.append("upload_status INT32 FIELD, ");
                sql.append("import_status INT32 FIELD, ");
                sql.append("create_time TIMESTAMP FIELD, ");
                sql.append("update_time TIMESTAMP FIELD, ");
                sql.append("upload_time TIMESTAMP FIELD, ");
                sql.append("import_time TIMESTAMP FIELD, ");
                sql.append("retry_time INT32 FIELD, ");
                sql.append("binary_file BLOB FIELD");
                sql.append(")");

                tempSession.executeNonQueryStatement(sql.toString());
                log.info("文件记录表创建成功: {}", tableName);
                
            } finally {
                if (tempSession != null) {
                    try {
                        tempSession.close();
            } catch (Exception e) {
                        log.warn("关闭临时Session失败: {}", e.getMessage());
                    }
                }
            }

        } catch (IoTDBConnectionException | StatementExecutionException e) {
                if (e.getMessage().contains("already exists")) {
                log.info("文件记录表已存在: {}，跳过创建步骤", tableName);
                } else {
                log.error("创建文件记录表失败: {}", tableName, e);
                throw e;
            }
        }
    }





    /**
     * 删除文件记录（表模型）
     */
    public boolean deleteFile(String fileName) {
        try {
            log.info("正在删除文件: {}", fileName);

            // 表模型删除语法，使用ALIGN BY DEVICE
            String deleteInfoSql = String.format(
                    "DELETE FROM %s WHERE file_name = '%s' ALIGN BY DEVICE",
                    FILE_INFO_DEVICE, fileName);

            // 删除文件内容（表模型语法）
            String deleteContentSql = String.format(
                    "DELETE FROM %s WHERE file_name = '%s' ALIGN BY DEVICE",
                    FILE_CONTENT_DEVICE, fileName);


            // 执行删除操作
            sessionPool.executeNonQueryStatement(deleteInfoSql);
            sessionPool.executeNonQueryStatement(deleteContentSql);

            return true;

        } catch (Exception e) {
            log.error("删除文件失败: {}", fileName, e);
            return false;
        }
    }

    /**
     * 根据file_name查询record_id列表（表模型）
     * 
     * @param fileName 文件名
     * @return record_id列表
     */
    public Map<String, Object> queryRecordIdsByFileName(String fileName) {
        Map<String, Object> result = new HashMap<>();
        List<String> recordIds = new ArrayList<>();
        
        if (sessionPool == null) {
            log.warn("IoTDB SessionPool不可用，无法查询record_id列表");
            result.put("success", false);
            result.put("message", "IoTDB SessionPool不可用");
            result.put("recordIds", recordIds);
            return result;
        }
        
        try {
            if (fileName == null || fileName.trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "file_name不能为空");
                result.put("recordIds", recordIds);
                return result;
            }
            
            log.info("正在根据file_name查询record_id列表: {}", fileName);
            
            // 使用临时Session执行查询
            Session tempSession = new Session.Builder()
                    .host(iotdbConfig.getHost())
                    .port(iotdbConfig.getPort())
                    .username(iotdbConfig.getUsername())
                    .password(iotdbConfig.getPassword())
                    .build();
            
            try {
                tempSession.open();
                
                // 设置SQL方言为TABLE（确保使用表模型）
                String setDialectSql = "SET SQL_DIALECT=TABLE";
                tempSession.executeNonQueryStatement(setDialectSql);
                
                // 使用目标数据库
                String useDbSql = "USE " + database;
                tempSession.executeNonQueryStatement(useDbSql);
                
                // 构建查询语句 - 根据file_name查询record_id
                String querySql = String.format(
                    "SELECT record_id FROM %s WHERE file_name = '%s'",
                    tableName, fileName.replace("'", "''"));
                
                // 执行查询 - 使用Object类型避免类型导入问题
                Object dataSetObj = tempSession.executeQueryStatement(querySql);
                
                // 获取反射方法（在try块外部定义以便finally块使用）
                java.lang.reflect.Method closeOperationHandleMethod = null;
                
                try {
                    // 使用反射获取方法（避免类型导入问题）
                    java.lang.reflect.Method getColumnNamesMethod = dataSetObj.getClass().getMethod("getColumnNames");
                    @SuppressWarnings("unchecked")
                    List<String> columnNames = (List<String>) getColumnNamesMethod.invoke(dataSetObj);
                    
                    // 获取hasNext和next方法
                    java.lang.reflect.Method hasNextMethod = dataSetObj.getClass().getMethod("hasNext");
                    java.lang.reflect.Method nextMethod = dataSetObj.getClass().getMethod("next");
                    closeOperationHandleMethod = dataSetObj.getClass().getMethod("closeOperationHandle");
                    
                    // 解析查询结果
                    while ((Boolean) hasNextMethod.invoke(dataSetObj)) {
                        Object recordObj = nextMethod.invoke(dataSetObj);
                        
                        // 使用反射获取字段值
                        String recordId = null;
                        
                        try {
                            // 获取RowRecord的方法
                            java.lang.reflect.Method getFieldsMethod = recordObj.getClass().getMethod("getFields");
                            java.util.List<?> fields = (java.util.List<?>) getFieldsMethod.invoke(recordObj);
                            
                            // 遍历字段
                            for (int i = 0; i < columnNames.size() && i < fields.size(); i++) {
                                String columnName = columnNames.get(i);
                                Object fieldValue = fields.get(i);
                                
                                if (fieldValue == null) {
                                    continue;
                                }
                                
                                // 检查字段是否为null
                                java.lang.reflect.Method isNullMethod = fieldValue.getClass().getMethod("isNull");
                                Boolean isNull = (Boolean) isNullMethod.invoke(fieldValue);
                                if (isNull != null && isNull) {
                                    continue;
                                }
                                
                                if ("record_id".equalsIgnoreCase(columnName)) {
                                    java.lang.reflect.Method getStringValueMethod = fieldValue.getClass().getMethod("getStringValue");
                                    recordId = (String) getStringValueMethod.invoke(fieldValue);
                                    if (recordId != null && !recordId.trim().isEmpty()) {
                                        recordIds.add(recordId);
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.warn("解析查询结果时发生异常", e);
                        }
                    }
                    
                    // 关闭查询结果集
                    if (closeOperationHandleMethod != null) {
                        closeOperationHandleMethod.invoke(dataSetObj);
                    }
                    
                } catch (Exception e) {
                    log.error("处理查询结果时发生异常", e);
                    if (closeOperationHandleMethod != null) {
                        try {
                            closeOperationHandleMethod.invoke(dataSetObj);
                        } catch (Exception ex) {
                            log.warn("关闭查询结果集失败", ex);
                        }
                    }
                }
                
                result.put("success", true);
                result.put("message", "查询成功");
                result.put("recordIds", recordIds);
                result.put("count", recordIds.size());
                log.info("根据file_name查询record_id列表成功，找到{}条记录", recordIds.size());
                
            } finally {
                if (tempSession != null) {
                    try {
                        tempSession.close();
                    } catch (Exception e) {
                        log.warn("关闭临时Session失败: {}", e.getMessage());
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("根据file_name查询record_id列表失败: {}", fileName, e);
            result.put("success", false);
            result.put("message", "查询失败: " + e.getMessage());
            result.put("recordIds", recordIds);
        }
        
        return result;
    }

    /**
     * 根据record_id删除文件记录（表模型）
     * 
     * @param recordId 记录唯一标识（UUID）
     * @return 删除结果
     */
    public Map<String, Object> deleteFileByRecordId(String recordId) {
        Map<String, Object> result = new HashMap<>();
        
        if (sessionPool == null) {
            log.warn("IoTDB SessionPool不可用，无法删除记录");
            result.put("success", false);
            result.put("message", "IoTDB SessionPool不可用");
            return result;
        }
        
        try {
            if (recordId == null || recordId.trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "record_id不能为空");
                return result;
            }

            log.info("正在根据record_id删除文件记录: {}", recordId);

            // 使用临时Session执行删除，确保使用表模型
            Session tempSession = new Session.Builder()
                    .host(iotdbConfig.getHost())
                    .port(iotdbConfig.getPort())
                    .username(iotdbConfig.getUsername())
                    .password(iotdbConfig.getPassword())
                    .build();
            
            try {
                tempSession.open();
                
                // 设置SQL方言为TABLE（确保使用表模型）
                String setDialectSql = "SET SQL_DIALECT=TABLE";
                tempSession.executeNonQueryStatement(setDialectSql);
                
                // 使用目标数据库
                String useDbSql = "USE " + database;
                tempSession.executeNonQueryStatement(useDbSql);
                
                // record_id现在是TAG列，可以直接在DELETE的WHERE条件中使用
                // 参考文档：https://iotdb.apache.org/zh/UserGuide/latest-Table/Basic-Concept/Delete-Data.html
                // DELETE语句的WHERE条件可以使用时间条件或标签条件（TAG列）
                
                // 直接使用record_id作为删除条件
                String deleteSql = String.format(
                        "DELETE FROM %s WHERE record_id = '%s'",
                        tableName, recordId.replace("'", "''"));
                
                log.info("删除SQL（表模型）: {}", deleteSql);
                
                // 执行删除操作
                tempSession.executeNonQueryStatement(deleteSql);
                
                result.put("success", true);
                result.put("message", "删除成功");
                result.put("recordId", recordId);
                log.info("根据record_id删除文件记录成功: {}", recordId);

            } finally {
                if (tempSession != null) {
                    try {
                        tempSession.close();
                    } catch (Exception e) {
                        log.warn("关闭临时Session失败: {}", e.getMessage());
                    }
                }
            }

        } catch (Exception e) {
            log.error("根据record_id删除文件记录失败: {}", recordId, e);
            result.put("success", false);
            result.put("message", "删除失败: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 批量导入文件到IoTDB的root.plpm.file_content表中（支持MultipartFile和FileRecordVO）
     * 包含文件基本信息和二进制文件内容
     */
    public Map<String, Object> batchImportFilesToIoTDB(List<com.plpm.vo.FileRecordVO> fileRecordVOs) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> importResults = new ArrayList<>();
        int successCount = 0;
        int failCount = 0;

        try {
            log.info("开始批量导入文件到IoTDB，文件数量: {}", 
                    fileRecordVOs != null ? fileRecordVOs.size() : 0);

            // 注意：参数验证已在Controller层完成，这里直接处理业务逻辑
            int fileCount = fileRecordVOs != null ? fileRecordVOs.size() : 0;

            // 使用批量插入优化性能，避免频繁的数据库连接
            Map<String, Object> batchResult = batchInsertFilesToIoTDB(fileRecordVOs);
            
            // 处理批量插入结果
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> batchResults = (List<Map<String, Object>>) batchResult.get("results");
            if (batchResults != null) {
                importResults.addAll(batchResults);
                for (Map<String, Object> fileResult : batchResults) {
                    if ((Boolean) fileResult.get("success")) {
                        successCount++;
                    } else {
                        failCount++;
                    }
                }
            }

            result.put("success", true);
            result.put("message", String.format("批量导入完成，成功: %d, 失败: %d", successCount, failCount));
            result.put("totalCount", fileCount);
            result.put("successCount", successCount);
            result.put("failCount", failCount);
            result.put("importResults", importResults);

            log.info("批量导入完成，成功: {}, 失败: {}", successCount, failCount);

        } catch (Exception e) {
            log.error("批量导入文件到IoTDB失败", e);
            result.put("success", false);
            result.put("message", "批量导入失败: " + e.getMessage());
            result.put("totalCount", fileRecordVOs != null ? fileRecordVOs.size() : 0);
            result.put("successCount", successCount);
            result.put("failCount", failCount);
            result.put("importResults", importResults);
        }

        return result;
    }



    /**
     * 批量插入文件到IoTDB
     * 使用批量操作，避免频繁的数据库连接
     */
    private Map<String, Object> batchInsertFilesToIoTDB(List<com.plpm.vo.FileRecordVO> fileRecordVOs) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> importResults = new ArrayList<>();
        
        if (sessionPool == null) {
            log.error("IoTDB SessionPool不可用，无法进行批量插入");
            result.put("success", false);
            result.put("message", "IoTDB连接不可用");
            result.put("results", importResults);
            return result;
        }

        try {
            int fileCount = fileRecordVOs != null ? fileRecordVOs.size() : 0;
            
            log.info("开始批量插入文件到IoTDB，文件数量: {}", fileCount);


            // 处理每个文件的数据准备
            for (int i = 0; i < fileCount; i++) {
                com.plpm.vo.FileRecordVO fileRecordVO = fileRecordVOs.get(i);
                Map<String, Object> fileResult = prepareSingleFileData(fileRecordVO);
                
                if ((Boolean) fileResult.get("success")) {
                    // 准备插入数据
                    long timestamp = (Long) fileResult.get("timestamp");
                    @SuppressWarnings("unchecked")
                    Map<String, Object> recordData = (Map<String, Object>) fileResult.get("recordData");
                    
                    try {
                        // 插入到IoTDB表模型
                        insertFileRecordToTable(timestamp, recordData);
                        importResults.add(fileResult);
                } catch (Exception e) {
                        log.error("插入文件记录到IoTDB失败: {}", fileRecordVO.getFileName(), e);
                    fileResult.put("success", false);
                        fileResult.put("message", "插入IoTDB失败: " + e.getMessage());
                        importResults.add(fileResult);
                }
                } else {
                importResults.add(fileResult);
            }
            }

            result.put("success", true);
            result.put("message", "批量插入完成");
            result.put("results", importResults);

        } catch (Exception e) {
            log.error("批量插入文件到IoTDB失败", e);
            result.put("success", false);
            result.put("message", "批量插入失败: " + e.getMessage());
            result.put("results", importResults);
        }

        return result;
    }


    /**
     * 准备单个文件的数据（表模型格式）
     */
    private Map<String, Object> prepareSingleFileData(com.plpm.vo.FileRecordVO fileRecordVO) {
        Map<String, Object> fileResult = new HashMap<>();
        String fileName = fileRecordVO.getFileName();

        try {
            // 生成时间戳
            long timestamp = System.currentTimeMillis();
            
            // 生成唯一标识UUID（32位，去除横线）
            String recordId = java.util.UUID.randomUUID().toString().replace("-", "");

            // 准备表模型数据
            Map<String, Object> recordData = new HashMap<>();
            
            // 添加唯一标识
            recordData.put("record_id", recordId);

            // 添加文件基本信息
            recordData.put("file_name", fileName);
            recordData.put("project_no", fileRecordVO.getProjectNo() != null ? fileRecordVO.getProjectNo() : "");
            recordData.put("plane_id", fileRecordVO.getPlaneId() != null ? fileRecordVO.getPlaneId() : "");
            recordData.put("plane_no", fileRecordVO.getPlaneNo() != null ? fileRecordVO.getPlaneNo() : "");
            recordData.put("place", fileRecordVO.getPlace() != null ? fileRecordVO.getPlace() : "");
            recordData.put("company", fileRecordVO.getCompany() != null ? fileRecordVO.getCompany() : "");
            recordData.put("product_phase", fileRecordVO.getProductPhase() != null ? fileRecordVO.getProductPhase() : 0);
            recordData.put("data_type_first", fileRecordVO.getDataTypeFirst() != null ? fileRecordVO.getDataTypeFirst() : 0);
            recordData.put("data_type_second", fileRecordVO.getDataTypeSecond() != null ? fileRecordVO.getDataTypeSecond() : 0);
            recordData.put("data_source", fileRecordVO.getDataSource() != null ? fileRecordVO.getDataSource() : "");
            recordData.put("start_time", fileRecordVO.getStartTime() != null ? fileRecordVO.getStartTime().atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli() : 0L);
            recordData.put("engine_id", fileRecordVO.getEngineId() != null ? fileRecordVO.getEngineId() : "");
            recordData.put("engine_no", fileRecordVO.getEngineNo() != null ? fileRecordVO.getEngineNo() : "");
            recordData.put("channel_no", fileRecordVO.getChannelNo() != null ? fileRecordVO.getChannelNo() : "");
            // 处理 device_no 字段
            String deviceNo = fileRecordVO.getDeviceNo() != null ? fileRecordVO.getDeviceNo() : "";
            recordData.put("device_no", deviceNo);
            log.info("准备文件数据 - 文件名: {}, deviceNo: '{}' (长度: {})", fileName, deviceNo, deviceNo != null ? deviceNo.length() : 0);
            if (deviceNo == null || deviceNo.trim().isEmpty()) {
                log.warn("警告：文件 {} 的 deviceNo 为空或空字符串", fileName);
            }
            recordData.put("engine_place", fileRecordVO.getEnginePlace() != null ? fileRecordVO.getEnginePlace() : "");
            recordData.put("ecu_id", fileRecordVO.getEcuId() != null ? fileRecordVO.getEcuId() : "");
            recordData.put("ecu_no", fileRecordVO.getEcuNo() != null ? fileRecordVO.getEcuNo() : "");
            recordData.put("ecu_sys_id", fileRecordVO.getEcuSysId() != null ? fileRecordVO.getEcuSysId() : "");
            recordData.put("ecu_sys_no", fileRecordVO.getEcuSysNo() != null ? fileRecordVO.getEcuSysNo() : "");
            recordData.put("subject", fileRecordVO.getSubject() != null ? fileRecordVO.getSubject() : "");
            recordData.put("remark", fileRecordVO.getRemark() != null ? fileRecordVO.getRemark() : "");
            recordData.put("check_code", fileRecordVO.getCheckCode() != null ? fileRecordVO.getCheckCode() : "");
            recordData.put("sync_data_source", fileRecordVO.getSyncDataSource() != null ? fileRecordVO.getSyncDataSource() : 0);
            recordData.put("sync_status", fileRecordVO.getSyncStatus() != null ? fileRecordVO.getSyncStatus() : 0);
            recordData.put("upload_status", fileRecordVO.getUploadStatus() != null ? fileRecordVO.getUploadStatus() : 0);
            recordData.put("import_status", 1); // 默认导入状态为1（成功）
            // 时间格式化器
            java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            java.time.LocalDateTime now = java.time.LocalDateTime.now();
            
            // 时间字段处理
            recordData.put("create_time", formatDateTime(fileRecordVO.getCreateTime(), now, formatter));
            recordData.put("update_time", formatDateTime(fileRecordVO.getUpdateTime(), now, formatter));
            recordData.put("upload_time", formatDateTime(fileRecordVO.getUploadTime(), now, formatter));
            recordData.put("import_time", now.format(formatter));
            recordData.put("retry_time", fileRecordVO.getRetryTime() != null ? fileRecordVO.getRetryTime() : 0);
            recordData.put("binary_file", fileRecordVO.getBinaryFile() != null ? fileRecordVO.getBinaryFile() : "".getBytes());

            fileResult.put("fileName", fileName);
                fileResult.put("success", true);
            fileResult.put("timestamp", timestamp);
            fileResult.put("recordData", recordData);

        } catch (Exception e) {
            log.error("准备单个文件数据失败，文件名: {}", fileName, e);
            fileResult.put("fileName", fileName);
            fileResult.put("success", false);
            fileResult.put("message", "准备文件数据失败: " + e.getMessage());
        }

        return fileResult;
    }

    /**
     * 将文件记录插入到IoTDB表模型中
     */
    private void insertFileRecordToTable(long timestamp, Map<String, Object> recordData) throws IoTDBConnectionException, StatementExecutionException {
        try {
            log.info("正在插入文件记录到表模型，时间戳: {}", timestamp);
            
            // 构建INSERT语句
            StringBuilder insertSql = new StringBuilder();
            insertSql.append("INSERT INTO ").append(tableName).append(" (time, ");
            
            // 添加字段名（包含唯一标识字段）
            String[] fieldNames = {
                "record_id",  // 唯一标识字段
                "file_name", "project_no", "plane_id", "plane_no", "place", "company", "product_phase", 
                "data_type_first", "data_type_second", "data_source", "start_time",
                "engine_id", "engine_no", "channel_no", "device_no", "engine_place", 
                "ecu_id", "ecu_no", "ecu_sys_id", "ecu_sys_no", "subject",
                "remark", "check_code", "sync_data_source", "sync_status", 
                "upload_status", "import_status", "create_time", "update_time", 
                "upload_time", "import_time", "retry_time", "binary_file"
            };
            
            for (int i = 0; i < fieldNames.length; i++) {
                if (i > 0) insertSql.append(", ");
                insertSql.append(fieldNames[i]);
            }
            insertSql.append(") VALUES (");
            
            // 添加时间戳
            insertSql.append(timestamp);
            
            // 添加字段值
            for (String fieldName : fieldNames) {
                Object value = recordData.get(fieldName);
                insertSql.append(", ");
                
                if (value == null) {
                    insertSql.append("NULL");
                } else if (value instanceof String) {
                    String strValue = value.toString();
                    insertSql.append("'").append(strValue.replace("'", "''")).append("'");
                } else if (value instanceof byte[]) {
                    // 对于BLOB字段，转换为十六进制字符串
                    byte[] bytes = (byte[]) value;
                    if (bytes.length == 0) {
                        insertSql.append("''");
                    } else {
                        insertSql.append("'").append(bytesToHex(bytes)).append("'");
                    }
                } else {
                    insertSql.append(value);
                }
            }
            insertSql.append(")");
            
            log.info("执行INSERT语句: {}", insertSql.toString());
            
            // 使用临时Session执行插入
            Session tempSession = new Session.Builder()
                    .host(iotdbConfig.getHost())
                    .port(iotdbConfig.getPort())
                    .username(iotdbConfig.getUsername())
                    .password(iotdbConfig.getPassword())
                    .build();
            try {
                tempSession.open();
                String setDialectSql = "SET SQL_DIALECT=TABLE";
                tempSession.executeNonQueryStatement(setDialectSql);
                String useDbSql = "USE " + database;
                tempSession.executeNonQueryStatement(useDbSql);
                tempSession.executeNonQueryStatement(insertSql.toString());
                log.info("文件记录插入成功，时间戳: {}", timestamp);
            } finally {
                if (tempSession != null) {
                    try {
                        tempSession.close();
                    } catch (Exception e) {
                        log.warn("关闭临时Session失败: {}", e.getMessage());
                    }
                }
            }

        } catch (Exception e) {
            log.error("插入文件记录到表模型失败，时间戳: {}", timestamp, e);
            throw new StatementExecutionException("插入文件记录失败: " + e.getMessage());
        }
    }

    /**
     * 将字节数组转换为十六进制字符串
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }

    /**
     * 格式化时间字段，如果为null则使用默认时间
     */
    private String formatDateTime(java.time.LocalDateTime dateTime, java.time.LocalDateTime defaultTime, java.time.format.DateTimeFormatter formatter) {
        return (dateTime != null ? dateTime : defaultTime).format(formatter);
    }

    /**
     * 查询文件列表（支持分页）
     * @param limit 限制返回的记录数
     * @param offset 偏移量
     * @return 文件信息列表
     */
    public List<com.plpm.model.FileInfo> queryFileList(int limit, int offset) {
        List<com.plpm.model.FileInfo> fileList = new ArrayList<>();
        
        if (sessionPool == null) {
            log.warn("IoTDB SessionPool不可用，无法查询文件列表");
            return fileList;
        }

        try {
            log.info("正在查询文件列表，limit={}, offset={}", limit, offset);
            
            // 使用临时Session执行查询
            Session tempSession = new Session.Builder()
                    .host(iotdbConfig.getHost())
                    .port(iotdbConfig.getPort())
                    .username(iotdbConfig.getUsername())
                    .password(iotdbConfig.getPassword())
                    .build();
            
            try {
                tempSession.open();
                
                // 设置SQL方言为TABLE（确保使用表模型）
                String setDialectSql = "SET SQL_DIALECT=TABLE";
                tempSession.executeNonQueryStatement(setDialectSql);
                
                // 使用目标数据库
                String useDbSql = "USE " + database;
                tempSession.executeNonQueryStatement(useDbSql);
                
                // 构建查询语句 - 查询文件列表，支持分页
                String querySql = String.format(
                    "SELECT file_name, upload_time FROM %s ORDER BY time DESC LIMIT %d OFFSET %d",
                    tableName, limit, offset);
                
                // 执行查询 - 使用Object类型避免类型导入问题
                Object dataSetObj = tempSession.executeQueryStatement(querySql);
                
                // 获取反射方法（在try块外部定义以便finally块使用）
                java.lang.reflect.Method closeOperationHandleMethod = null;
                
                try {
                    // 使用反射获取方法（避免类型导入问题）
                    java.lang.reflect.Method getColumnNamesMethod = dataSetObj.getClass().getMethod("getColumnNames");
                    @SuppressWarnings("unchecked")
                    List<String> columnNames = (List<String>) getColumnNamesMethod.invoke(dataSetObj);
                    
                    // 获取hasNext和next方法
                    java.lang.reflect.Method hasNextMethod = dataSetObj.getClass().getMethod("hasNext");
                    java.lang.reflect.Method nextMethod = dataSetObj.getClass().getMethod("next");
                    closeOperationHandleMethod = dataSetObj.getClass().getMethod("closeOperationHandle");
                    
                    // 解析查询结果
                    while ((Boolean) hasNextMethod.invoke(dataSetObj)) {
                        Object recordObj = nextMethod.invoke(dataSetObj);
                        
                        // 使用反射获取字段值（避免类型导入问题）
                        String fileName = null;
                        String uploadTimeStr = null;
                        
                        try {
                            // 获取RowRecord的方法
                            java.lang.reflect.Method getFieldsMethod = recordObj.getClass().getMethod("getFields");
                            java.util.List<?> fields = (java.util.List<?>) getFieldsMethod.invoke(recordObj);
                            
                            // 遍历字段
                            for (int i = 0; i < columnNames.size() && i < fields.size(); i++) {
                                String columnName = columnNames.get(i);
                                Object fieldValue = fields.get(i);
                                
                                if (fieldValue == null) {
                                    continue;
                                }
                                
                                // 检查字段是否为null
                                java.lang.reflect.Method isNullMethod = fieldValue.getClass().getMethod("isNull");
                                Boolean isNull = (Boolean) isNullMethod.invoke(fieldValue);
                                if (isNull != null && isNull) {
                                    continue;
                                }
                                
                                if ("file_name".equalsIgnoreCase(columnName)) {
                                    java.lang.reflect.Method getStringValueMethod = fieldValue.getClass().getMethod("getStringValue");
                                    fileName = (String) getStringValueMethod.invoke(fieldValue);
                                } else if ("upload_time".equalsIgnoreCase(columnName)) {
                                    // 尝试获取字符串值
                                    try {
                                        java.lang.reflect.Method getStringValueMethod = fieldValue.getClass().getMethod("getStringValue");
                                        uploadTimeStr = (String) getStringValueMethod.invoke(fieldValue);
                                    } catch (Exception e) {
                                        // 如果不是字符串类型，尝试获取长整型值
                                        try {
                                            java.lang.reflect.Method getLongValueMethod = fieldValue.getClass().getMethod("getLongValue");
                                            Long longValue = (Long) getLongValueMethod.invoke(fieldValue);
                                            uploadTimeStr = String.valueOf(longValue);
                                        } catch (Exception ex) {
                                            log.warn("无法解析upload_time字段值");
                                        }
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.warn("解析查询结果失败", e);
                            continue;
                        }
                        
                        // 创建FileInfo对象
                        if (fileName != null) {
                            com.plpm.model.FileInfo fileInfo = new com.plpm.model.FileInfo();
                            fileInfo.setFileName(fileName);
                            
                            // 解析上传时间
                            if (uploadTimeStr != null && !uploadTimeStr.isEmpty()) {
                                try {
                                    java.time.format.DateTimeFormatter formatter = 
                                        java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                                    java.time.LocalDateTime uploadTime = java.time.LocalDateTime.parse(uploadTimeStr, formatter);
                                    fileInfo.setUploadTime(uploadTime);
                                } catch (Exception e) {
                                    log.warn("解析上传时间失败: {}, 使用当前时间", uploadTimeStr);
                                    fileInfo.setUploadTime(java.time.LocalDateTime.now());
                                }
                            } else {
                                fileInfo.setUploadTime(java.time.LocalDateTime.now());
                            }
                            
                            fileInfo.setSource("UPLOAD");
                            fileInfo.setStatus("SUCCESS");
                            
                            fileList.add(fileInfo);
                        }
                    }
                } finally {
                    // 关闭查询结果集
                    if (closeOperationHandleMethod != null && dataSetObj != null) {
                        try {
                            closeOperationHandleMethod.invoke(dataSetObj);
                        } catch (Exception e) {
                            log.warn("关闭查询结果集失败", e);
                        }
                    }
                }
                
                log.info("查询文件列表成功，返回 {} 条记录", fileList.size());
                
            } finally {
                if (tempSession != null) {
                    try {
                        tempSession.close();
                    } catch (Exception e) {
                        log.warn("关闭临时Session失败: {}", e.getMessage());
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("查询文件列表失败", e);
            // 返回空列表而不是抛出异常，避免影响其他功能
        }
        
        return fileList;
    }

    

}